package com.ytjj.qmyx.supplychain.service;

import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
import java.util.List;

/**
 * @ClassName com.miu.service.AbstractService
 * @Description TODO
 * @Version 1.0
 **/
public abstract class AbstractService<M extends tk.mybatis.mapper.common.Mapper<T>, T> implements tk.mybatis.mapper.common.Mapper<T> {
    @Autowired
    protected M baseMapper;

    public M getBaseMapper() {
        return baseMapper;
    }

    @Override
    public T selectOne(T record) {
        return baseMapper.selectOne(record);
    }

    @Override
    public List<T> select(T record) {
        return baseMapper.select(record);
    }

    @Override
    public List<T> selectAll() {
        return baseMapper.selectAll();
    }

    @Override
    public int selectCount(T record) {
        return baseMapper.selectCount(record);
    }

    @Override
    public T selectByPrimaryKey(Object key) {
        return baseMapper.selectByPrimaryKey(key);
    }

    @Override
    public boolean existsWithPrimaryKey(Object key) {
        return baseMapper.existsWithPrimaryKey(key);
    }

    @Override
    @Transactional
    public int insert(T record) {
        return baseMapper.insert(record);
    }

    @Override
    @Transactional
    public int insertSelective(T record) {
        return baseMapper.insertSelective(record);
    }

    @Override
    @Transactional
    public int updateByPrimaryKey(T record) {
        return baseMapper.updateByPrimaryKey(record);
    }

    @Override
    @Transactional
    public int updateByPrimaryKeySelective(T record) {
        return baseMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    @Transactional
    public int delete(T record) {
        return baseMapper.delete(record);
    }

    @Override
    @Transactional
    public int deleteByPrimaryKey(Object key) {
        return baseMapper.deleteByPrimaryKey(key);
    }

    @Override
    public List<T> selectByExample(Object example) {
        return baseMapper.selectByExample(example);
    }

    @Override
    public T selectOneByExample(Object example) {
        return baseMapper.selectOneByExample(example);
    }

    @Override
    public int selectCountByExample(Object example) {
        return baseMapper.selectCountByExample(example);
    }

    @Override
    @Transactional
    public int deleteByExample(Object example) {
        return baseMapper.deleteByExample(example);
    }

    @Override
    @Transactional
    public int updateByExample(T record, Object example) {
        return baseMapper.updateByExample(record, example);
    }

    @Override
    @Transactional
    public int updateByExampleSelective(T record, Object example) {
        return baseMapper.updateByExampleSelective(record, example);
    }

    @Override
    public List<T> selectByExampleAndRowBounds(Object example, RowBounds rowBounds) {
        return baseMapper.selectByExampleAndRowBounds(example, rowBounds);
    }

    @Override
    public List<T> selectByRowBounds(T record, RowBounds rowBounds) {
        return baseMapper.selectByExampleAndRowBounds(record, rowBounds);
    }

    /**
     * @Description 批量增加
     * 
     * 
     */
    @Transactional
    public boolean insertBatch(List<T> records) {
        for (T record : records){
            if (this.insert(record) < 1){
                return false;
            }
        }
        return true;
    }

    /**
     * @Description 批量增加-选择性
     * 
     * 
     */
    @Transactional
    public boolean insertBatchSelective(List<T> records) {
        for (T record : records){
            if (this.insertSelective(record) < 1){
                return false;
            }
        }
        return true;
    }

    /**
     * @Description 批量修改-选择性
     */
    @Transactional
    public boolean updateBatchByPrimaryKeySelective(List<T> records) {
        for (T record : records){
            if (this.updateByPrimaryKeySelective(record) < 1){
                return false;
            }
        }
        return true;
    }

    /**
     * @Description 根据条件对象自动识别Add or Update操作
     * @Notice 判断是否存在的Example和Update的Example使用的是同一对象
     * 
     * 
     */
    @Transactional
    public int saveByExampleSelective(T record, Object example) {
        T obj = this.selectOneByExample(example);
        if (obj == null){
            return this.insertSelective(record);
        }else{
            return this.updateByExampleSelective(record, example);
        }
    }

    /**
     * @Description 根据主键值自动识别Add or Update操作
     * @Notice 如果为Add操作，且Table主键为自增型，请将record的主键字段设为Null。
     * 
     * 
     */
    @Transactional
    public int saveByPrimaryKeySelective(T record) {
        //提取主键值
        Object key = getPrimaryKey(record);
        if(key == null){
            return 0;	//解耦
        }
        //根据主键值查询DB，判断是否存在，并执行对应逻辑
        T obj = this.selectByPrimaryKey(key);
        if (obj == null){
            return this.insertSelective(record);
        }
        else{
            return this.updateByPrimaryKeySelective(record);
        }
    }

    /**
     * @Description 根据主键值自动识别Add or Update操作
     * @Notice 如果为Add操作，且Table主键为自增型，请将record的主键字段设为Null。
     * 
     * 
     */
    @Transactional
    public boolean saveBatchByPrimaryKeySelective(List<T> records) {
        for (T record : records){
            if (this.saveByPrimaryKeySelective(record) < 1){
                return false;
            }
        }
        return true;
    }

    /**
     * @Description	获取主键值
     * 
     * 
     */
    public Object getPrimaryKey(Object obj){
        Class<?> cls = obj.getClass();
        //得到所有属性
        Field[] fields = cls.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            try {
                //得到属性
                Field field = fields[i];
                //打开私有访问
                field.setAccessible(true);
                //判断属性是否带主键的注解
                if(field.isAnnotationPresent(javax.persistence.Id.class)){
                    //返回属性值
                    return field.get(obj);
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}
